Skip to content
Redirected from Dev ApiKey
created by Aha00aAha00a at 2026-05-26
last modified by Aha00aAha00a at 2026-09-15
revision: 3

Dev UserEmail

1. 설계 의도

  • 사용자의 identity는 이메일이 아니라 User.seq다. 한 사람이 여러 Google 이메일로 로그인하더라도 같은 User.seq에 연결되면 같은 사용자로 취급한다.
  • 로그인 가능한 이메일 목록은 UserEmail이 관리한다. 이메일은 로그인 수단이자 권한 actor 후보로만 사용한다.
  • 한 이메일은 하나의 user에만 연결된다. 이미 다른 user에 연결된 이메일을 현재 계정에 연결하려면, Google OAuth로 소유권을 확인한 뒤 사용자가 명시적으로 병합을 승인해야 한다.
  • 권한 평가는 단일 로그인 이메일이 아니라 현재 user에 연결된 모든 로그인 이메일 기준으로 수행한다. 따라서 기존 이메일 기반 permission은 여러 이메일을 가진 사용자에게도 자연스럽게 적용된다.

2. 정책

  • 초기 UI에서는 로그인 이메일 삭제를 제공하지 않는다. 최소 하나의 로그인 이메일은 migration, login, 계정 연결 flow에서 유지한다.
  • Google OAuth profile email만 로그인 이메일로 연결한다. Google People API의 여러 verified email을 자동 등록하지 않는다.
  • 대표 이메일은 UserEmail.isPrimary = true로 표현한다.
  • 병합 후 duplicate User row는 주요 FK와 UserEmail을 canonical User.seq로 이동한 뒤 삭제한다.

3. 구현 결과

  • User 모델은 이메일을 직접 갖지 않고, UserEmail 모델이 이메일 조회, 추가, primary 설정, 중복 확인을 담당한다. 로그인은 UserEmail.email로 user를 찾고, 없으면 새 User와 첫 UserEmail을 만든다.
  • 세션은 seq, nickname, loginEmail 중심으로 정리했다. identity 판단은 seq로 하고, loginEmail은 표시나 감사 목적의 보조 정보다. 다만 UserEmail 행이 하나도 없는 사용자에게는 WikiPermission 이 loginEmail 을 권한 actor 로 대신 쓴다.
  • 계정 설정 화면에 로그인 이메일 목록과 Google 계정 연결 버튼을 추가했다. 연결된 이메일이 다른 user 소유이면 병합 확인 화면으로 이동한다.
  • 병합 로직은 DB 메타데이터에서 User(seq) 참조 FK를 읽어 duplicate user의 참조를 canonical user로 옮긴다. UserEmail도 canonical user로 이동하고, 이동이 끝나면 duplicate User row를 삭제한다. 다만 (user, site) 유니크 키를 가진 테이블(UserSite·SiteAdmin)은 그대로 옮기면 키가 충돌하므로, canonical 이 이미 가진 site 는 duplicate 행을 지우고 나머지만 옮긴다.
  • Permission은 현재 user의 모든 로그인 이메일을 actor 후보로 사용하도록 변경했다. Exact, Domain, Login 권한이 여러 로그인 이메일 기준으로 동작한다.
  • UserMergeSpec가 FK 이동(Page, AccessLog), UserEmail 이동, primary 하나 유지, duplicate User 삭제, 그리고 두 사용자가 같은 site 의 관리자일 때 SiteAdmin 행이 충돌 없이 하나로 합쳐지는 것을 검증한다. (user, site) 충돌 처리는 UserMerge.mergeUniqueUserSiteRows 하나로 UserSite·SiteAdmin 에 함께 쓴다 — UserSite 는 evolution 55 가 지웠지만 테이블이 있을 때만 도는 가드 뒤에 남아 있고, SiteAdmin 은 2026-09-15 부터 같은 처리를 받는다. 전에는 SiteAdmin 겹침(둘 다 같은 site 관리자)이 primary key 를 위반해 병합 전체를 실패시켰다.

4. 운영 확인

배포 전에는 DB를 백업하고 staging에서 migration rehearsal을 수행한다. UserEmail.email unique 제약, 기존 user 수와 migration된 primary email 수, 현재 DB의 User(seq) 참조 FK 목록, Google OAuth Console의 /google/oauth/callback redirect URI 등록 여부를 확인한다.

배포 후에는 대표 계정의 여러 이메일로 각각 로그인하고, 관리자 권한, 이메일 기반 page permission, 계정 설정의 로그인 이메일 목록, 병합 flow를 확인한다.

5. See Also

5.2. Similar Pages

Similar pages by cosine similarity. Words after page name are term frequency.

  • 42.71% ToDo-User-Nickname-Change user(30:59), nickname(1:55), admin(5:21), 않는다(2:21), 같은(5:12), seq(3:14), 로그인(11:5), 현재(4:11), 관리자(2:12), 기존(2:12)
  • 33.50% ToDo NewUserFlow user(30:6), 로그인(11:10), site(10:2), google(7:5), 이메일(9:2), login(5:5), 권한(4:6), 같은(5:1), oauth(3:3), 설정(2:4)
  • 32.29% Dev SiteAdmin site(10:27), user(30:5), admin(5:25), seq(3:6), 같은(5:1), 권한(4:1), 추가했다(1:4), 기준으로(2:2), fk(2:1), 관리자(2:1)

5.3. Adjacent Pages

Control
≤ 32
all
1.0x
1.0x
80
-120
ON
Metrics
Nodes(visible/total)0/0
Links(visible/total)0/0
Avg degree0.00
Depth coverage0
Queue(fetch/graph)0 / 0
Zoom(scale)1.00x
Ctrl/⌘ + Scroll: Zoom
Root 1-hop 2-hop+